/**
 * The MIT License
 *
 * Copyright (c) 2010 Benjamin Klum
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package org.helgoboss.win32_facade;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.io.File;

import jnacontrib.win32.Registry;

import org.helgoboss.win32_facade.win32.ExtendedUser32;


public class Win32Facade {
	private static final String REGISTRY_KEY_TO_GLOBAL_ENV = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment";
    private static final String REGISTRY_KEY_TO_USER_ENV = "Environment";
    
    public static File getProgramFilesDir() {
        String programFilesDirString = System.getenv().get("PROGRAMFILES");
        if (programFilesDirString == null) {
            programFilesDirString = System.getenv().get("ProgramFiles");
        }
        return new File(programFilesDirString);
    }
	
	public static void addToPathVariable(PathScope scope, String pathComponent) {
		Set<String> components = getPathVariableComponents(scope);
		components.add(pathComponent);
		setPathVariableComponents(scope, components);
		refreshEnvironment();
	}
	
	public static void removeFromPathVariable(PathScope scope, String pathComponent) {
		Set<String> components = getPathVariableComponents(scope);
		components.remove(pathComponent);
		setPathVariableComponents(scope, components);
		refreshEnvironment();
	}
	
	
	/**
	 * @param components
	 */
	public static void setPathVariableComponents(PathScope scope, Set<String> components) {
		StringBuilder sb = new StringBuilder();
		boolean firstPath = true;
		for (String component: components) {
			if (firstPath) {
				firstPath = false;
			} else {
				sb.append(";");
			}
			sb.append(component);
		}
        setPathVariableContent(scope, sb.toString());
	}

	/**
	 * @param string
	 */
	public static void setPathVariableContent(PathScope scope, String content) {
		try {
			Registry.setStringValue(getRegistryRootKey(scope), getRegistryKeyToEnv(scope), "Path", content);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	public static Set<String> getPathVariableComponents(PathScope scope) {
		String content = getPathVariableContent(scope);
		Set<String> components = new HashSet<String>();
        if (content != null) {
            String[] componentArray = content.split(";");
            components.addAll(Arrays.asList(componentArray));
        }
		return components;
	}
	
	/**
	 * @return
	 */
	public static String getPathVariableContent(PathScope scope) {
		try {
			return Registry.getStringValue(getRegistryRootKey(scope), getRegistryKeyToEnv(scope), "Path");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	public static void refreshEnvironment() {
		ExtendedUser32 user32 = ExtendedUser32.INSTANCE;
		user32.SendMessageTimeoutA(ExtendedUser32.HWND_BROADCAST, ExtendedUser32.WM_SETTINGCHANGE, 0, "Environment",
				ExtendedUser32.SMTO_ABORTIFHUNG, 5000, 0); 
	}
    
    private static String getRegistryKeyToEnv(PathScope scope) {
        switch (scope) {
            case GLOBAL:
                return REGISTRY_KEY_TO_GLOBAL_ENV;
            case USER:
            default:
                return REGISTRY_KEY_TO_USER_ENV;
        }
    }
    
    private static Registry.REGISTRY_ROOT_KEY getRegistryRootKey(PathScope scope) {
        switch (scope) {
            case GLOBAL:
                return Registry.REGISTRY_ROOT_KEY.LOCAL_MACHINE;
            case USER:
            default:
                return Registry.REGISTRY_ROOT_KEY.CURRENT_USER;
        }
    }
    
}
